#include <iostream>
#include <iomanip>
//#include <string>
#include <map>
#include <algorithm>

using namespace std;

//function object as sorting criterion for multimap
class RuntimeStringCmp {
public:
  enum cmp_mode {normal, nocase}; //as static const int
private:
  const cmp_mode mode;
  static bool nocase_compare(char c1, char c2) { return toupper(c1)<toupper(c2);}
public:
  //constructor:initialize the comparison criterion
  RuntimeStringCmp(cmp_mode m = normal) : mode(m){}
  //the comparison function operator overloading
  bool operator() (const string& s1, const string& s2) const {
    if (mode == normal) {
      return s1<s2;
    }
    else {
      return lexicographical_compare(s1.begin(),s1.end(),
				     s2.begin(),s2.end(),
				     nocase_compare);
    }
  }
};
//multimap instantiation
typedef multimap<string,string,RuntimeStringCmp> StringStringMap;
//fill a multimap
void fill(StringStringMap& m)
{
  m.clear();
  m.insert(make_pair("Deutschland","Germany"));
  m.insert(make_pair("deutsch","German"));
  m.insert(make_pair("Haken","snag"));
  m.insert(make_pair("arbeiten","work"));
  m.insert(make_pair("Hund","dog"));
  m.insert(make_pair("gehen","go"));
  m.insert(make_pair("Unternehmen","enterprise"));
  m.insert(make_pair("unternehmen","undertake"));
  m.insert(make_pair("gehen","walk"));
  m.insert(make_pair("Bestatter","undertaker"));

  return;
}
template<typename T>
void print(T& t)
{
  typename T::iterator iter;
  cout.setf(ios::left, ios::adjustfield);
  for(iter=t.begin();iter!=t.end();++iter) {
    cout<<setw(15)<<iter->first<<iter->second<<endl;
  }
}
//main as driver
//copy multimaps between different sorting criterion
int main()
{
  StringStringMap m_case;
  fill(m_case);
  print(m_case);
  cout<<setfill('-')<<setw(30)<<""<<setfill(' ')<<endl;

  RuntimeStringCmp ignore_case(RuntimeStringCmp::nocase);
  StringStringMap m_nocase(m_case.begin(),m_case.end(),ignore_case);
  //  StringStringMap m_nocase(ignore_case);
  //  m_nocase = m_case;
  //error: non-static const member 'RuntimeStringCmp mode'
  //can't use default assignment operator
  print(m_nocase);

  StringStringMap::iterator iter;
  iter = m_nocase.find("gehen");
  cout<<iter->first<<"\t"<<iter->second<<endl;
  cout<<m_nocase.count("gehen")<<endl;
  cout<<m_nocase.count("a")<<endl;
  return 0;
}
